import { growthCurve, keepDecimal, random } from "@/util/util";
import { monstersMap } from "@/const/monster";
import { SysInfo } from "@/const/sys";
import { SysActionTypes } from "@/store/sys/action-types";
import { MutationTypes } from "@/store/player/mutation-types";
import { useStore } from "@/store/index";
import { batchGenerateEquip } from "@/const/equips/equipment";
import { equiptoPackItem } from "@/const/equips/equipmentType";
import {
  PlayerBattleProperty,
  PlayerStatusOptionType
} from "@/store/player/types";
import { PlayerActionTypes } from "@/store/player/action-types";
const store = useStore();
const playerDDR = (DEF: number, ATK: number) => {
  const difDEF = Math.max(Math.ceil(DEF - ATK), -500);
  return keepDecimal(1 - difDEF / (difDEF + 1000), 4);
};
const getMonsterList = (monster: any[]) => {
  return monster.map(({ level, monsterId }, index) => {
    const monsterData = monstersMap.get(monsterId);
    if (!monsterData) return null;
    const { coin, name, props, growth, drops, mount, grade } = monsterData;
    const addition = growthCurve(level, growth);
    const CHP = Math.ceil(addition * props.CHP);
    const DMG = keepDecimal(addition * props.ATK, 2);
    const DEF = keepDecimal(addition * props.DEF, 2);
    const AS = props.AS;
    const additonCoin = coin.map((m: number) => keepDecimal(addition * m, 0));
    return {
      name: `${name}[${index + 1}号]`,
      level,
      drops,
      mount,
      grade,
      coin: additonCoin,
      CHP,
      DMG,
      DEF,
      AS
    };
  });
};
const playerDMG = (player: any) => {
  const { ATK, CRR, CRD } = player;
  const random = Math.random();
  const isCrit = random < CRR;
  if (isCrit) {
    return { ATK: Math.ceil(ATK * CRD), isCrit };
  }
  return { ATK, isCrit };
};
const inflictPlayer = (CHP: number, DMG: number) => {
  const HP = CHP + DMG;
  if (HP < 0) {
    return 0;
  }
  return HP;
};
export const fightCalc = (monster: any[]) => {
  return new Promise(res => {
    const monsterNum = monster.length;
    let killNum = 0;
    const player: PlayerBattleProperty = store.getters.playerBattleProperty;
    const monsterList = getMonsterList(monster);
    const monsterTxt = monsterList
      .map(m => {
        if (!m) return null;
        return `${m.name}(${m.level}级)`;
      })
      .filter(m => m)
      .join("，");
    store.dispatch(
      SysActionTypes.SYS_PUSH_INFO,
      new SysInfo(`遭遇 ${monsterTxt}，战斗吧！`, 3)
    );
    monsterList.forEach(m => {
      if (m) {
        const timer = setInterval(() => {
          const PLAYER_CHP = store.getters.userPropertyCHP;
          if (PLAYER_CHP <= 0 || m.CHP <= 0) {
            clearInterval(timer);
            return;
          }
          const DMG = Math.round(-m.DMG * playerDDR(player.DEF, m.DMG));
          const isMonsterCrit = Math.random() <= 0.2;
          let FINALDMG = DMG;
          if (isMonsterCrit) {
            FINALDMG = Math.ceil(DMG * 1.5);
          }
          const isMonsterCRStr = isMonsterCrit ? "暴击" : "";
          store.dispatch(
            SysActionTypes.SYS_PUSH_INFO,
            new SysInfo(
              `${m.name}(${m.level}级)对你造成 ${Math.abs(
                FINALDMG
              )} 点${isMonsterCRStr}伤害`,
              1
            )
          );
          store.dispatch(PlayerActionTypes.PLAYER_SET_STATUS, {
            type: PlayerStatusOptionType.HP,
            value: FINALDMG
          });
        }, Math.ceil(1000 / m.AS));
      }
    });
    const timerP = setInterval(() => {
      if (killNum === monsterNum) {
        clearInterval(timerP);
        res(true);
        return;
      }
      const PLAYER_CHP = store.getters.userPropertyCHP;
      if (PLAYER_CHP <= 0) {
        clearInterval(timerP);
        res(false);
        return;
      }
      const PLAYER_DMG = playerDMG(player);
      // const m = monsterList[killNum];
      const mIndex = random(0, monsterList.length - 1);
      const m = monsterList[mIndex];
      if (m) {
        const DMG = Math.round(-PLAYER_DMG.ATK * playerDDR(m.DEF, player.ATK));
        m.CHP = inflictPlayer(m.CHP, DMG);
        const isCRStr = PLAYER_DMG.isCrit ? "暴击" : "";
        store.dispatch(
          SysActionTypes.SYS_PUSH_INFO,
          new SysInfo(
            `你对${m.name}(${m.level}级)造成 ${Math.abs(DMG)} 点${isCRStr}伤害`,
            4
          )
        );
        if (m.CHP <= 0) {
          killNum++;
          store.dispatch(
            SysActionTypes.SYS_PUSH_INFO,
            new SysInfo(`你击杀了${m.name}(${m.level}级)`, 4)
          );
          const options = {
            type: m.drops,
            level: m.level,
            grade: m.grade,
            mount: m.mount
          };
          const equipments = batchGenerateEquip(options);
          equipments.forEach(async m => {
            const data = await store.dispatch(SysActionTypes.SYS_ADD_EQUIP, m);
            store.commit(
              MutationTypes.PUT_ITEM_TO_PACKAGE,
              equiptoPackItem(data)
            );
          });
          const getCoin = random(m.coin[0], m.coin[1]);
          store.commit(MutationTypes.MAKE_MONEY, getCoin);
          store.dispatch(
            SysActionTypes.SYS_PUSH_INFO,
            new SysInfo(`你获得了${getCoin}金币`, 4, equipments)
          );
          monsterList.splice(mIndex, 1);
        }
      } else {
        killNum++;
        monsterList.splice(mIndex, 1);
      }
    }, Math.ceil(1000 / player.AS));
  });
};
